package model;

import java.util.HashMap;
import java.util.Map;

/**
 * Tile class represents one movement square within the game world.
 * Each tile stores a list of neighbouring tiles, as well as a flag
 * which stores whether the tile has been visited by the player or not.
 * 
 * @author Alexander Craig
 */
public class Tile {
	
	/** stores whether the tile has been visited by the player */
	private boolean visited;
	/** stores the x coordinate of the tile in relation to the maze grid */
	private int xCoord;
	/** stores the y coordinate of the tile in relation to the maze grid */
	private int yCoord;
	/** the list of possible exits from the tile (only cardinal direction allowed) */
	private Map<Direction, Tile> exits;
	
	/**
	 * Constructs a new tile at the given coordinates.
	 * The new tile has no neighbours, and has not been visited.
	 * @param x	the x coordinate of the tile
	 * @param y	the y coordinate of the tile
	 */
	public Tile(int x, int y) {
		xCoord = x;
		yCoord = y;
		exits = new HashMap<Direction, Tile>();
		visited = false;
	}
	
	/**
	 * @return true if the tile has not been visited, false if it has
	 */
	public boolean hasDot() {
		return !visited;
	}
	
	/**
	 * @return the x coordinate of the tile in relation to the maze grid
	 */
	public int getXCoord() {
		return xCoord;
	}
	
	/**
	 * @return the y coordinate of the tile in relation to the maze grid
	 */
	public int getYCoord() {
		return yCoord;
	}
	
	/**
	 * Sets the visited status of the tile to true (ie. no dot should be drawn).
	 */
	public void clearDot() {
		visited = true;
	}
	
	/**
	 * Sets the visited status of the tile to false (ie. a dot should be drawn)
	 */
	public void resetDot() {
		visited = false;
	}
	
	/**
	 * Sets the visited status of the tile
	 */
	public void setVisited(Boolean b) {
		visited = b;
	}
	
	/**
	 * Adds an exit to the tile. An exit may not be added to a direction with
	 * an existing exit unless the original exit is removed first.
	 * @param dir	the direction in which to add an exit
	 * @param tile	the tile that this direction should exit to
	 * @return	returns true if the add was successful, false if a
	 * 			duplicate key was encountered
	 */
	public boolean setExit(Direction dir, Tile tile) {
		exits.put(dir, tile);
		return true;
	}
	
	/**
	 * Removes a given exit from the tile.
	 * @param dir	the direction in which to remove a tile.
	 * @return	false if the exit did not exist, true otherwise
	 */
	public boolean removeExit(Direction dir) {
		return (exits.remove(dir) != null);
	}
	
	/**
	 * Gets the exit in the specified direction.
	 * @param dir	the direction to search for an exit in
	 * @return	returns the tile in the given direction, or null
	 * 			if no exit exists
	 */
	public Tile getExit(Direction dir) {
		return exits.get(dir);
	}
	
	/**
	 * Returns of a string of the tile's x and y coordinates. Mostly for
	 * debug purposes.
	 * @return	a string in the format of "Tile X:n Y:n"
	 */
	public String shortName() {
		return "Tile X:" + getXCoord() + " Y:" + getYCoord() + "\n";
	}
	
	/**
	 * @return a long string description of the tile and it's exits
	 */
	public String toString() {
		String returnString = shortName();
		for(Direction dir : Direction.values()) {
			if (exits.get(dir) != null) {
				returnString += dir + ": " + exits.get(dir).shortName();
			} else {
				returnString += dir + ": Wall\n";
			}
		}
		return returnString;
	}
}
